#include <avr/interrupt.h>
#include <avr/io.h>
#include <stdio.h>
#include "usart.h"

FILE usartstdout;

void usart_init(long int clock, long int baudrate)
{
	UCSRB |= (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);   // Turn on the transmission and reception circuitry
	UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes

	baudrate = (clock/16/baudrate - 1);
	UBRRL = baudrate; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
	UBRRH = (baudrate >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
}

char rxbyte()
{
	while ((UCSRA & (1 << RXC)) == 0) ; // Do nothing until data have been recieved and is ready to be read from UDR
	return UDR;
}

void txbyte(char b)
{
	while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
	UDR = b;
}

int txchar(char c, FILE *stream)
{
	if(c=='\n')
		txchar('\r',stream);
	txbyte(c);
	return 0;
}

void usart_setup_stdio()
{
	fdev_setup_stream(&usartstdout,txchar, NULL,_FDEV_SETUP_WRITE);
	stdout = &usartstdout;
}

ISR(USART_RXC_vect)
{
	usart_rx_callback(rxbyte());
}
